Load libraries

library(Seurat)
library(Matrix)
library(dplyr)
library(RColorBrewer)
library(ggplot2)
library(ggExtra)
library(cowplot)
library(reticulate)
library(wesanderson)
library(princurve)
use_python("/usr/bin/python3")

#Set ggplot theme as classic
theme_set(theme_classic())

Load the raw counts matrix

Countdata <- Read10X("../../RawData/Gmnc_KO/outs/filtered_feature_bc_matrix/")

Raw.data <- CreateSeuratObject(counts = Countdata,
                              project = "Gmnc_KO",
                              min.cells = 3,
                              min.features = 800)

Raw.data$Barcodes <- rownames(Raw.data@meta.data)

rm(Countdata)

dim(Raw.data)
## [1] 21077 16272
Raw.data$percent.mito <- PercentageFeatureSet(Raw.data, pattern = "^mt-")
Raw.data$percent.ribo <- PercentageFeatureSet(Raw.data, pattern = "(^Rpl|^Rps|^Mrp)")
VlnPlot(object = Raw.data, features = c("nFeature_RNA","nCount_RNA", "percent.mito", "percent.ribo"), ncol= 2) & NoAxes()

# Inspect cell based on relation between nUMI and nGene detected

# Relation between nUMI and nGene detected
Cell.QC.Stat <- Raw.data@meta.data

p1 <- ggplot(Cell.QC.Stat, aes(x=nCount_RNA, y=nFeature_RNA)) + geom_point() + geom_smooth(method="lm")
p1 <- ggMarginal(p1, type = "histogram", fill="lightgrey")

p2 <- ggplot(Cell.QC.Stat, aes(x=log10(nCount_RNA), y=log10(nFeature_RNA))) + geom_point() + geom_smooth(method="lm")
p2 <- ggMarginal(p2, type = "histogram", fill="lightgrey")

plot_grid(plotlist = list(p1,p2), ncol=2, align='h', rel_widths = c(1, 1)) ; rm(p1,p2)

Cells with deviating nGene/nUMI ratio display an Erythrocyte signature

Raw.data <- AddModuleScore(Raw.data,
                           features = list(c("Hbb-bt", "Hbq1a", "Isg20", "Fech", "Snca", "Rec114")),
                           ctrl = 10,
                           name = "Erythrocyte.signature")

Cell.QC.Stat$Erythrocyte.signature <- Raw.data$Erythrocyte.signature1
gradient <- colorRampPalette(brewer.pal(n =11, name = "Spectral"))(100)

p1 <- ggplot(Cell.QC.Stat, aes(log10(nCount_RNA), y=log10(nFeature_RNA))) +
      geom_point(aes(color= Erythrocyte.signature))  + 
      scale_color_gradientn(colours=rev(gradient), name='Erythrocyte score') + theme(legend.position="none")

p2 <- ggplot(Cell.QC.Stat, aes(log10(nCount_RNA), y=log10(nFeature_RNA))) +
      geom_point(aes(color= percent.mito))  + 
      scale_color_gradientn(colours=rev(gradient), name='Percent mito') + theme(legend.position="none")

p3 <- ggplot(Cell.QC.Stat, aes(log10(nCount_RNA), y=log10(nFeature_RNA))) +
      geom_point(aes(color= percent.ribo))  + 
      scale_color_gradientn(colours=rev(gradient), name='Percent ribo') + theme(legend.position="none")

p1 + p2 + p3

## Exclude Erythrocytes

Cell.QC.Stat$Erythrocyte <- ifelse(Cell.QC.Stat$Erythrocyte.signature > 0.1, "Erythrocyte", "Not_Erythrocyte")
p2 <- ggplot(Cell.QC.Stat, aes(x=log10(nCount_RNA), y=log10(nFeature_RNA))) +
  geom_point(aes(colour = Erythrocyte)) +
  theme(legend.position="none")

ggMarginal(p2, type = "histogram", fill="lightgrey")

# Filter cells based on these thresholds
Cell.QC.Stat <- Cell.QC.Stat %>% filter(Cell.QC.Stat$Erythrocyte.signature < 0.1)

Low quality cell filtering

Filtering cells based on percentage of mitochondrial transcripts

We applied a high and low median absolute deviation (mad) thresholds to exclude outlier cells

max.mito.thr <- median(Cell.QC.Stat$percent.mito) + 3*mad(Cell.QC.Stat$percent.mito)
min.mito.thr <- median(Cell.QC.Stat$percent.mito) - 3*mad(Cell.QC.Stat$percent.mito)
p1 <- ggplot(Cell.QC.Stat, aes(x=nFeature_RNA, y=percent.mito)) +
  geom_point() +
  geom_hline(aes(yintercept = max.mito.thr), colour = "red", linetype = 2) +
  geom_hline(aes(yintercept = min.mito.thr), colour = "red", linetype = 2) +
  annotate(geom = "text", label = paste0(as.numeric(table(Cell.QC.Stat$percent.mito > max.mito.thr | Cell.QC.Stat$percent.mito < min.mito.thr)[2])," cells removed\n",
                                         as.numeric(table(Cell.QC.Stat$percent.mito > max.mito.thr | Cell.QC.Stat$percent.mito < min.mito.thr)[1])," cells remain"),
           x = 6000, y = 20)

ggMarginal(p1, type = "histogram", fill="lightgrey", bins=100) 

# Filter cells based on these thresholds
Cell.QC.Stat <- Cell.QC.Stat %>% filter(percent.mito < max.mito.thr) %>% filter(percent.mito > min.mito.thr)

Filtering cells based on number of genes and transcripts detected

Remove cells with to few gene detected or with to many UMI counts

We filter cells which are likely to be doublet based on their higher content of transcript detected as well as cell with to few genes/UMI sequenced

# Set low and hight thresholds on the number of detected genes based on the one obtain with the WT dataset
min.Genes.thr <- log10(1635)
max.Genes.thr <- log10(8069)

# Set hight threshold on the number of transcripts
max.nUMI.thr <- log10(58958)
# Gene/UMI scatter plot before filtering
p1 <- ggplot(Cell.QC.Stat, aes(x=log10(nCount_RNA), y=log10(nFeature_RNA))) +
  geom_point() +
  geom_smooth(method="lm") +
  geom_hline(aes(yintercept = min.Genes.thr), colour = "green", linetype = 2) +
  geom_hline(aes(yintercept = max.Genes.thr), colour = "green", linetype = 2) +
  geom_vline(aes(xintercept = max.nUMI.thr), colour = "red", linetype = 2)

ggMarginal(p1, type = "histogram", fill="lightgrey")

# Filter cells base on both metrics
Cell.QC.Stat <- Cell.QC.Stat %>% filter(log10(nFeature_RNA) > min.Genes.thr) %>% filter(log10(nCount_RNA) < max.nUMI.thr)

Filter cells below the main population nUMI/nGene relationship

lm.model <- lm(data = Cell.QC.Stat, formula = log10(nFeature_RNA) ~ log10(nCount_RNA))

p2 <- ggplot(Cell.QC.Stat, aes(x=log10(nCount_RNA), y=log10(nFeature_RNA))) +
  geom_point() +
  geom_smooth(method="lm") +
  geom_hline(aes(yintercept = min.Genes.thr), colour = "green", linetype = 2) +
  geom_hline(aes(yintercept = max.Genes.thr), colour = "green", linetype = 2) +
  geom_vline(aes(xintercept = max.nUMI.thr), colour = "red", linetype = 2) +
  annotate(geom = "text", label = paste0(dim(Cell.QC.Stat)[1], " QC passed cells"), x = 4, y = 3.8)

ggMarginal(p2, type = "histogram", fill="lightgrey")

## Filter the Seurat object

Raw.data <- subset(x = Raw.data, subset = Barcodes %in%  Cell.QC.Stat$Barcodes)
# Plot final QC metrics
VlnPlot(object = Raw.data, features = c("nFeature_RNA","nCount_RNA", "percent.mito", "percent.ribo"), ncol= 2) & NoAxes()

p1 <- ggplot(Raw.data@meta.data, aes(x=log10(nCount_RNA), y=log10(nFeature_RNA))) + geom_point() + geom_smooth(method="lm")
ggMarginal(p1, type = "histogram", fill="lightgrey")

rm(list = ls()[!ls() %in% "Raw.data"])

Use Scrublet to detect obvious doublets

Run Scrublet with default parameter

Export raw count matrix as input to Scrublet

#Export filtered matrix
dir.create("../../RawData/Gmnc_KO/Scrublet_inputs")

exprData <- Matrix(as.matrix(Raw.data@assays[["RNA"]]@counts), sparse = TRUE)
writeMM(exprData, "../../RawData/Gmnc_KO/Scrublet_inputs/matrix1.mtx")
## NULL
import scrublet as scr
import scipy.io
import numpy as np
import os

#Load raw counts matrix and gene list
input_dir = '../../RawData/Gmnc_KO/Scrublet_inputs'
counts_matrix = scipy.io.mmread(input_dir + '/matrix1.mtx').T.tocsc()

#Initialize Scrublet
scrub = scr.Scrublet(counts_matrix,
                     expected_doublet_rate=0.1,
                     sim_doublet_ratio=2,
                     n_neighbors = 8)

#Run the default pipeline
doublet_scores, predicted_doublets = scrub.scrub_doublets(min_counts=1, 
                                                          min_cells=3, 
                                                          min_gene_variability_pctl=85, 
                                                          n_prin_comps=25)
## Preprocessing...
## Simulating doublets...
## Embedding transcriptomes using PCA...
## Calculating doublet scores...
## Automatically set threshold at doublet score = 0.35
## Detected doublet rate = 3.7%
## Estimated detectable doublet fraction = 26.0%
## Overall doublet rate:
##  Expected   = 10.0%
##  Estimated  = 14.2%
## Elapsed time: 21.3 seconds
# Import scrublet's doublet score
Raw.data$Doubletscore <- py$doublet_scores

# Plot doublet score
ggplot(Raw.data@meta.data, aes(x = Doubletscore, stat(ndensity))) +
  geom_histogram(bins = 200, colour ="lightgrey")+
  geom_vline(xintercept = 0.15, colour = "red", linetype = 2)

# Manually set threshold at doublet score to 0.2
Raw.data$Predicted_doublets <- ifelse(py$doublet_scores > 0.15, "Doublet","Singlet")
table(Raw.data$Predicted_doublets)
## 
## Doublet Singlet 
##    2273   10215
Raw.data <- subset(x = Raw.data, subset = Predicted_doublets == "Singlet")

Generate SRING dimentionality reduction

Export counts matrix

dir.create("./SpringCoordinates")
# Export raw expression matrix and gene list to regenerate a spring plot
exprData <- Matrix(as.matrix(Raw.data@assays[["RNA"]]@counts), sparse = TRUE)
writeMM(exprData, "./SpringCoordinates/ExprData.mtx")
## NULL
Genelist <- row.names(Raw.data@assays[["RNA"]]@counts)
write.table(Genelist, "./SpringCoordinates/Genelist.csv", sep="\t", col.names = F, row.names = F, quote = F)
#Export metadata
Scrublet <- c("Scrublet", Raw.data$Predicted_doublets)
Scrublet <- paste(Scrublet, sep=",", collapse=",")

Cellgrouping <- Scrublet
write.table(Cellgrouping, "./SpringCoordinates/Cellgrouping.csv", quote =F, row.names = F, col.names = F)

Import coordinates

spring.coor <- read.table("SpringCoordinates/coordinates.txt", sep = ",", header = F, row.names = 1)
colnames(spring.coor) <- c("Spring_1", "Spring_2")
Spring.Sym <- function(x){
  x = abs(max(spring.coor$Spring_2)-x)
 }

spring.coor$Spring_2 <- sapply(spring.coor$Spring_2, function(x) Spring.Sym(x))
Raw.data$Spring_1 <- spring.coor$Spring_1
Raw.data$Spring_2 <- spring.coor$Spring_2
spring <- as.matrix(Raw.data@meta.data %>% select("Spring_1", "Spring_2"))
  
Raw.data[["spring"]] <- CreateDimReducObject(embeddings = spring, key = "Spring_", assay = DefaultAssay(Raw.data))
DimPlot(Raw.data, 
        reduction = "spring",
        pt.size = 0.5) & NoAxes()

# Sctransform normalization

Raw.data <- SCTransform(Raw.data,
                        method = "glmGamPoi",
                        vars.to.regress = c("percent.mito"),
                        verbose = T)
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |======================================================================| 100%
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |=====                                                                 |   8%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |===========                                                           |  15%
  |                                                                            
  |=============                                                         |  18%
  |                                                                            
  |==============                                                        |  21%
  |                                                                            
  |================                                                      |  23%
  |                                                                            
  |==================                                                    |  26%
  |                                                                            
  |====================                                                  |  28%
  |                                                                            
  |======================                                                |  31%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |=========================                                             |  36%
  |                                                                            
  |===========================                                           |  38%
  |                                                                            
  |=============================                                         |  41%
  |                                                                            
  |===============================                                       |  44%
  |                                                                            
  |================================                                      |  46%
  |                                                                            
  |==================================                                    |  49%
  |                                                                            
  |====================================                                  |  51%
  |                                                                            
  |======================================                                |  54%
  |                                                                            
  |=======================================                               |  56%
  |                                                                            
  |=========================================                             |  59%
  |                                                                            
  |===========================================                           |  62%
  |                                                                            
  |=============================================                         |  64%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |================================================                      |  69%
  |                                                                            
  |==================================================                    |  72%
  |                                                                            
  |====================================================                  |  74%
  |                                                                            
  |======================================================                |  77%
  |                                                                            
  |========================================================              |  79%
  |                                                                            
  |=========================================================             |  82%
  |                                                                            
  |===========================================================           |  85%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |=================================================================     |  92%
  |                                                                            
  |==================================================================    |  95%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |=====                                                                 |   8%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |===========                                                           |  15%
  |                                                                            
  |=============                                                         |  18%
  |                                                                            
  |==============                                                        |  21%
  |                                                                            
  |================                                                      |  23%
  |                                                                            
  |==================                                                    |  26%
  |                                                                            
  |====================                                                  |  28%
  |                                                                            
  |======================                                                |  31%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |=========================                                             |  36%
  |                                                                            
  |===========================                                           |  38%
  |                                                                            
  |=============================                                         |  41%
  |                                                                            
  |===============================                                       |  44%
  |                                                                            
  |================================                                      |  46%
  |                                                                            
  |==================================                                    |  49%
  |                                                                            
  |====================================                                  |  51%
  |                                                                            
  |======================================                                |  54%
  |                                                                            
  |=======================================                               |  56%
  |                                                                            
  |=========================================                             |  59%
  |                                                                            
  |===========================================                           |  62%
  |                                                                            
  |=============================================                         |  64%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |================================================                      |  69%
  |                                                                            
  |==================================================                    |  72%
  |                                                                            
  |====================================================                  |  74%
  |                                                                            
  |======================================================                |  77%
  |                                                                            
  |========================================================              |  79%
  |                                                                            
  |=========================================================             |  82%
  |                                                                            
  |===========================================================           |  85%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |=================================================================     |  92%
  |                                                                            
  |==================================================================    |  95%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%

Run PCA and broad clustering

Raw.data <- RunPCA(Raw.data, verbose = FALSE)

Raw.data <- FindNeighbors(Raw.data,
                          dims = 1:20,
                          k.param = 8)

Raw.data <- FindClusters(Raw.data, resolution = 0.2)
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
## 
## Number of nodes: 10215
## Number of edges: 218490
## 
## Running Louvain algorithm...
## Maximum modularity in 10 random starts: 0.9335
## Number of communities: 9
## Elapsed time: 1 seconds
DimPlot(Raw.data,
        reduction = "spring",
        cols = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#d14c8d", "#4cabdc", "#5ab793", "#e7823a", "#046c9a", "#4990c9"),
        pt.size = 0.5) & NoAxes()

Raw.data$Broadclust.ident <- Raw.data$seurat_clusters

Differentiating neurons sub-clustering

Extract differentiating neurons

Neurons.data <-  subset(Raw.data, idents = 3)

DimPlot(Neurons.data,
        reduction = "spring",
        pt.size = 1,
        cols =  c("#cc3a1b")) + NoAxes()

## Fit pseudotime

fit <- principal_curve(as.matrix(Neurons.data@meta.data[,c("Spring_1", "Spring_2")]),
                       smoother='lowess',
                       trace=TRUE,
                       f = 1,
                       stretch=0)
## Starting curve---distance^2: 84204082853
## Iteration 1---distance^2: 46039577
## Iteration 2---distance^2: 42955956
## Iteration 3---distance^2: 41286356
## Iteration 4---distance^2: 40749859
## Iteration 5---distance^2: 40679459
## Iteration 6---distance^2: 40714117
#Pseudotime score
PseudotimeScore <- fit$lambda/max(fit$lambda)

if (cor(PseudotimeScore, Neurons.data@assays$SCT@data['Hmga2', ]) > 0) {
  Neurons.data$PseudotimeScore <- -(PseudotimeScore - max(PseudotimeScore))
}

cols <- brewer.pal(n =11, name = "Spectral")

ggplot(Neurons.data@meta.data, aes(Spring_1, Spring_2)) +
  geom_point(aes(color=PseudotimeScore), size=2, shape=16) + 
  scale_color_gradientn(colours=rev(cols), name='Pseudotime score')

## Regress pseudotime and cluster cells into lineages

Neurons.data <- SCTransform(Neurons.data,
                            method = "glmGamPoi",
                            vars.to.regress = c("PseudotimeScore", "nFeature_RNA"),
                            verbose = T)
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |======================================================================| 100%
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |=====                                                                 |   7%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |============                                                          |  17%
  |                                                                            
  |==============                                                        |  20%
  |                                                                            
  |================                                                      |  23%
  |                                                                            
  |===================                                                   |  27%
  |                                                                            
  |=====================                                                 |  30%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |============================                                          |  40%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |=====================================                                 |  53%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |==========================================                            |  60%
  |                                                                            
  |============================================                          |  63%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |=================================================                     |  70%
  |                                                                            
  |===================================================                   |  73%
  |                                                                            
  |======================================================                |  77%
  |                                                                            
  |========================================================              |  80%
  |                                                                            
  |==========================================================            |  83%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |=================================================================     |  93%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |=====                                                                 |   7%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |============                                                          |  17%
  |                                                                            
  |==============                                                        |  20%
  |                                                                            
  |================                                                      |  23%
  |                                                                            
  |===================                                                   |  27%
  |                                                                            
  |=====================                                                 |  30%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |============================                                          |  40%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |=====================================                                 |  53%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |==========================================                            |  60%
  |                                                                            
  |============================================                          |  63%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |=================================================                     |  70%
  |                                                                            
  |===================================================                   |  73%
  |                                                                            
  |======================================================                |  77%
  |                                                                            
  |========================================================              |  80%
  |                                                                            
  |==========================================================            |  83%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |=================================================================     |  93%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |======================================================================| 100%

We used on transcription factors expression profile to perform lineage clustering

TFs <- read.table("TF.csv", sep = ";")[,1]

Neurons.data <- RunPCA(Neurons.data,
                       features = TFs,
                       verbose = FALSE)
Neurons.data <- FindNeighbors(Neurons.data,
                          dims = c(1:10),
                          k.param = 6)

Neurons.data <- FindClusters(Neurons.data, resolution = 0.2)
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
## 
## Number of nodes: 1659
## Number of edges: 22850
## 
## Running Louvain algorithm...
## Maximum modularity in 10 random starts: 0.8550
## Number of communities: 3
## Elapsed time: 0 seconds
DimPlot(Neurons.data,
        reduction = "spring",
        cols = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#d14c8d", "#4cabdc", "#5ab793", "#e7823a", "#046c9a", "#4990c9"),
        pt.size = 0.5) & NoAxes()

FeaturePlot(object = Neurons.data,
            features = c("Foxg1", "Zfpm2",
                         "Lhx1", "Zic5", "Zfp503"),
            pt.size = 0.2,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "spring",
            order = T) & NoAxes() & NoLegend()

Raw.data$Broadclust.ident <- sapply(Raw.data$Barcodes,
                              FUN = function(x) {
                                if (x %in% Neurons.data$Barcodes) {
                                  x = paste0("Neuron_",Neurons.data@meta.data[x, "seurat_clusters"])
                                } else {
                                  x = Raw.data@meta.data[x, "Broadclust.ident"]
                                  }
                              })
DimPlot(Raw.data,
        reduction = "spring",
        group.by = "Broadclust.ident",
        cols = c("#ebcb2e", "#9ec22f", "#a9961b", "#cc3a1b", "#d14c8d", "#4cabdc", "#5ab793", "grey90", "#e7823a", "#046c9a", "#4990c9"),
        pt.size = 0.5) & NoAxes()

Plot marker genes found in the WT dataset

FeaturePlot(object = Raw.data,
            features = c("Tbr1","Foxg1", "Trp73", "Htr2c",
                         "Shisa2", "Wif1", "Rassf4","Dkk3",
                         "Dlk1", "Sulf1", "Ttr", "Fgf8", "Fgf17",
                         "Foxc1", "C1qb"),
            pt.size = 0.2,
            cols = c("grey90", brewer.pal(9,"YlGnBu")),
            reduction = "spring",
            order = T) & NoAxes() & NoLegend()

Save the object

saveRDS(Raw.data, "./GmncKO.cells.RDS")

Session Info

#date
format(Sys.time(), "%d %B, %Y, %H,%M")
## [1] "22 avril, 2022, 15,15"
#Packages used
sessionInfo()
## R version 4.1.3 (2022-03-10)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /home/matthieu/anaconda3/lib/libmkl_rt.so.1
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] princurve_2.1.6    wesanderson_0.3.6  reticulate_1.22    cowplot_1.1.1     
##  [5] ggExtra_0.9        ggplot2_3.3.5      RColorBrewer_1.1-2 dplyr_1.0.7       
##  [9] Matrix_1.4-1       SeuratObject_4.0.4 Seurat_4.0.5      
## 
## loaded via a namespace (and not attached):
##   [1] Rtsne_0.15                  colorspace_2.0-2           
##   [3] deldir_1.0-6                ellipsis_0.3.2             
##   [5] ggridges_0.5.3              XVector_0.34.0             
##   [7] GenomicRanges_1.46.1        spatstat.data_2.1-0        
##   [9] farver_2.1.0                leiden_0.3.9               
##  [11] listenv_0.8.0               ggrepel_0.9.1              
##  [13] fansi_0.5.0                 sparseMatrixStats_1.6.0    
##  [15] codetools_0.2-18            splines_4.1.3              
##  [17] knitr_1.36                  polyclip_1.10-0            
##  [19] jsonlite_1.7.2              ica_1.0-2                  
##  [21] cluster_2.1.3               png_0.1-7                  
##  [23] uwot_0.1.10                 shiny_1.7.1                
##  [25] sctransform_0.3.2           spatstat.sparse_2.0-0      
##  [27] compiler_4.1.3              httr_1.4.2                 
##  [29] assertthat_0.2.1            fastmap_1.1.0              
##  [31] lazyeval_0.2.2              later_1.3.0                
##  [33] htmltools_0.5.2             tools_4.1.3                
##  [35] igraph_1.2.11               GenomeInfoDbData_1.2.7     
##  [37] gtable_0.3.0                glue_1.5.1                 
##  [39] RANN_2.6.1                  reshape2_1.4.4             
##  [41] Rcpp_1.0.8                  Biobase_2.54.0             
##  [43] scattermore_0.7             jquerylib_0.1.4            
##  [45] vctrs_0.3.8                 nlme_3.1-153               
##  [47] DelayedMatrixStats_1.16.0   lmtest_0.9-39              
##  [49] xfun_0.28                   stringr_1.4.0              
##  [51] globals_0.14.0              mime_0.12                  
##  [53] miniUI_0.1.1.1              lifecycle_1.0.1            
##  [55] irlba_2.3.3                 goftest_1.2-3              
##  [57] future_1.23.0               zlibbioc_1.40.0            
##  [59] MASS_7.3-56                 zoo_1.8-9                  
##  [61] scales_1.1.1                spatstat.core_2.3-1        
##  [63] MatrixGenerics_1.6.0        promises_1.2.0.1           
##  [65] spatstat.utils_2.2-0        SummarizedExperiment_1.24.0
##  [67] parallel_4.1.3              yaml_2.2.1                 
##  [69] pbapply_1.5-0               gridExtra_2.3              
##  [71] sass_0.4.0                  rpart_4.1.16               
##  [73] stringi_1.7.6               highr_0.9                  
##  [75] S4Vectors_0.32.3            BiocGenerics_0.40.0        
##  [77] GenomeInfoDb_1.30.0         bitops_1.0-7               
##  [79] rlang_0.4.12                pkgconfig_2.0.3            
##  [81] matrixStats_0.61.0          glmGamPoi_1.6.0            
##  [83] evaluate_0.14               lattice_0.20-45            
##  [85] ROCR_1.0-11                 purrr_0.3.4                
##  [87] tensor_1.5                  labeling_0.4.2             
##  [89] patchwork_1.1.1             htmlwidgets_1.5.4          
##  [91] tidyselect_1.1.1            parallelly_1.29.0          
##  [93] RcppAnnoy_0.0.19            plyr_1.8.6                 
##  [95] magrittr_2.0.2              R6_2.5.1                   
##  [97] IRanges_2.28.0              generics_0.1.1             
##  [99] DelayedArray_0.20.0         DBI_1.1.1                  
## [101] pillar_1.6.4                withr_2.4.3                
## [103] mgcv_1.8-40                 fitdistrplus_1.1-6         
## [105] RCurl_1.98-1.5              survival_3.2-13            
## [107] abind_1.4-5                 tibble_3.1.6               
## [109] future.apply_1.8.1          crayon_1.4.2               
## [111] KernSmooth_2.23-20          utf8_1.2.2                 
## [113] spatstat.geom_2.3-0         plotly_4.10.0              
## [115] rmarkdown_2.11              grid_4.1.3                 
## [117] data.table_1.14.2           digest_0.6.29              
## [119] xtable_1.8-4                tidyr_1.1.4                
## [121] httpuv_1.6.3                stats4_4.1.3               
## [123] munsell_0.5.0               viridisLite_0.4.0          
## [125] bslib_0.3.1

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France, ↩︎

LS0tCnRpdGxlOiAiR21uYyBLTyBxdWFsaXR5IGNvbnRyb2wiCmF1dGhvcjoKICAgLSBNYXR0aGlldSBNb3JlYXVeW0luc3RpdHV0ZSBvZiBQc3ljaGlhdHJ5IGFuZCBOZXVyb3NjaWVuY2Ugb2YgUGFyaXMsIElOU0VSTSBVMTI2NiwgNzUwMTQsIFBhcmlzLCBGcmFuY2UsIG1hdHRoaWV1Lm1vcmVhdUBpbnNlcm0uZnJdIFshW10oaHR0cHM6Ly9vcmNpZC5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9pbWFnZXMvb3JjaWRfMTZ4MTYucG5nKV0oaHR0cHM6Ly9vcmNpZC5vcmcvMDAwMC0wMDAyLTI1OTItMjM3MykKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6IAogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBkZl9wcmludDogdGliYmxlCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRoZW1lOiBjb3NtbwogICAgY3NzOiAiLi4vc3R5bGUuY3NzIgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZS5sYXp5ID0gRkFMU0UpCmBgYAoKIyBMb2FkIGxpYnJhcmllcwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoTWF0cml4KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHByaW5jdXJ2ZSkKdXNlX3B5dGhvbigiL3Vzci9iaW4vcHl0aG9uMyIpCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKIyBMb2FkIHRoZSByYXcgY291bnRzIG1hdHJpeAoKYGBge3J9CkNvdW50ZGF0YSA8LSBSZWFkMTBYKCIuLi8uLi9SYXdEYXRhL0dtbmNfS08vb3V0cy9maWx0ZXJlZF9mZWF0dXJlX2JjX21hdHJpeC8iKQoKUmF3LmRhdGEgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IENvdW50ZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJHbW5jX0tPIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmNlbGxzID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLmZlYXR1cmVzID0gODAwKQoKUmF3LmRhdGEkQmFyY29kZXMgPC0gcm93bmFtZXMoUmF3LmRhdGFAbWV0YS5kYXRhKQoKcm0oQ291bnRkYXRhKQoKZGltKFJhdy5kYXRhKQpgYGAKYGBge3J9ClJhdy5kYXRhJHBlcmNlbnQubWl0byA8LSBQZXJjZW50YWdlRmVhdHVyZVNldChSYXcuZGF0YSwgcGF0dGVybiA9ICJebXQtIikKUmF3LmRhdGEkcGVyY2VudC5yaWJvIDwtIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KFJhdy5kYXRhLCBwYXR0ZXJuID0gIiheUnBsfF5ScHN8Xk1ycCkiKQpgYGAKCmBgYHtyfQpWbG5QbG90KG9iamVjdCA9IFJhdy5kYXRhLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsIm5Db3VudF9STkEiLCAicGVyY2VudC5taXRvIiwgInBlcmNlbnQucmlibyIpLCBuY29sPSAyKSAmIE5vQXhlcygpCmBgYAojIEluc3BlY3QgY2VsbCBiYXNlZCBvbiByZWxhdGlvbiBiZXR3ZWVuIG5VTUkgYW5kIG5HZW5lIGRldGVjdGVkCgpgYGB7cn0KIyBSZWxhdGlvbiBiZXR3ZWVuIG5VTUkgYW5kIG5HZW5lIGRldGVjdGVkCkNlbGwuUUMuU3RhdCA8LSBSYXcuZGF0YUBtZXRhLmRhdGEKCnAxIDwtIGdncGxvdChDZWxsLlFDLlN0YXQsIGFlcyh4PW5Db3VudF9STkEsIHk9bkZlYXR1cmVfUk5BKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikKcDEgPC0gZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKQoKcDIgPC0gZ2dwbG90KENlbGwuUUMuU3RhdCwgYWVzKHg9bG9nMTAobkNvdW50X1JOQSksIHk9bG9nMTAobkZlYXR1cmVfUk5BKSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpCnAyIDwtIGdnTWFyZ2luYWwocDIsIHR5cGUgPSAiaGlzdG9ncmFtIiwgZmlsbD0ibGlnaHRncmV5IikKCnBsb3RfZ3JpZChwbG90bGlzdCA9IGxpc3QocDEscDIpLCBuY29sPTIsIGFsaWduPSdoJywgcmVsX3dpZHRocyA9IGMoMSwgMSkpIDsgcm0ocDEscDIpCmBgYAoKQ2VsbHMgd2l0aCBkZXZpYXRpbmcgbkdlbmUvblVNSSByYXRpbyBkaXNwbGF5IGFuIEVyeXRocm9jeXRlIHNpZ25hdHVyZSAKCgpgYGB7cn0KUmF3LmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoUmF3LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChjKCJIYmItYnQiLCAiSGJxMWEiLCAiSXNnMjAiLCAiRmVjaCIsICJTbmNhIiwgIlJlYzExNCIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY3RybCA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkVyeXRocm9jeXRlLnNpZ25hdHVyZSIpCgpDZWxsLlFDLlN0YXQkRXJ5dGhyb2N5dGUuc2lnbmF0dXJlIDwtIFJhdy5kYXRhJEVyeXRocm9jeXRlLnNpZ25hdHVyZTEKYGBgCgpgYGB7cn0KZ3JhZGllbnQgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikpKDEwMCkKCnAxIDwtIGdncGxvdChDZWxsLlFDLlN0YXQsIGFlcyhsb2cxMChuQ291bnRfUk5BKSwgeT1sb2cxMChuRmVhdHVyZV9STkEpKSkgKwogICAgICBnZW9tX3BvaW50KGFlcyhjb2xvcj0gRXJ5dGhyb2N5dGUuc2lnbmF0dXJlKSkgICsgCiAgICAgIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihncmFkaWVudCksIG5hbWU9J0VyeXRocm9jeXRlIHNjb3JlJykgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKcDIgPC0gZ2dwbG90KENlbGwuUUMuU3RhdCwgYWVzKGxvZzEwKG5Db3VudF9STkEpLCB5PWxvZzEwKG5GZWF0dXJlX1JOQSkpKSArCiAgICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPSBwZXJjZW50Lm1pdG8pKSAgKyAKICAgICAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnM9cmV2KGdyYWRpZW50KSwgbmFtZT0nUGVyY2VudCBtaXRvJykgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKcDMgPC0gZ2dwbG90KENlbGwuUUMuU3RhdCwgYWVzKGxvZzEwKG5Db3VudF9STkEpLCB5PWxvZzEwKG5GZWF0dXJlX1JOQSkpKSArCiAgICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yPSBwZXJjZW50LnJpYm8pKSAgKyAKICAgICAgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG91cnM9cmV2KGdyYWRpZW50KSwgbmFtZT0nUGVyY2VudCByaWJvJykgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKcDEgKyBwMiArIHAzCmBgYAojIyBFeGNsdWRlIEVyeXRocm9jeXRlcwoKYGBge3J9CkNlbGwuUUMuU3RhdCRFcnl0aHJvY3l0ZSA8LSBpZmVsc2UoQ2VsbC5RQy5TdGF0JEVyeXRocm9jeXRlLnNpZ25hdHVyZSA+IDAuMSwgIkVyeXRocm9jeXRlIiwgIk5vdF9Fcnl0aHJvY3l0ZSIpCmBgYAoKYGBge3J9CnAyIDwtIGdncGxvdChDZWxsLlFDLlN0YXQsIGFlcyh4PWxvZzEwKG5Db3VudF9STkEpLCB5PWxvZzEwKG5GZWF0dXJlX1JOQSkpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gRXJ5dGhyb2N5dGUpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdnTWFyZ2luYWwocDIsIHR5cGUgPSAiaGlzdG9ncmFtIiwgZmlsbD0ibGlnaHRncmV5IikKYGBgCgpgYGB7cn0KIyBGaWx0ZXIgY2VsbHMgYmFzZWQgb24gdGhlc2UgdGhyZXNob2xkcwpDZWxsLlFDLlN0YXQgPC0gQ2VsbC5RQy5TdGF0ICU+JSBmaWx0ZXIoQ2VsbC5RQy5TdGF0JEVyeXRocm9jeXRlLnNpZ25hdHVyZSA8IDAuMSkKYGBgCgojIExvdyBxdWFsaXR5IGNlbGwgZmlsdGVyaW5nCgojIyBGaWx0ZXJpbmcgY2VsbHMgYmFzZWQgb24gcGVyY2VudGFnZSBvZiBtaXRvY2hvbmRyaWFsIHRyYW5zY3JpcHRzCgpXZSBhcHBsaWVkIGEgaGlnaCBhbmQgbG93IG1lZGlhbiBhYnNvbHV0ZSBkZXZpYXRpb24gKG1hZCkgdGhyZXNob2xkcyB0byBleGNsdWRlIG91dGxpZXIgY2VsbHMKCmBgYHtyfQptYXgubWl0by50aHIgPC0gbWVkaWFuKENlbGwuUUMuU3RhdCRwZXJjZW50Lm1pdG8pICsgMyptYWQoQ2VsbC5RQy5TdGF0JHBlcmNlbnQubWl0bykKbWluLm1pdG8udGhyIDwtIG1lZGlhbihDZWxsLlFDLlN0YXQkcGVyY2VudC5taXRvKSAtIDMqbWFkKENlbGwuUUMuU3RhdCRwZXJjZW50Lm1pdG8pCmBgYAoKYGBge3J9CnAxIDwtIGdncGxvdChDZWxsLlFDLlN0YXQsIGFlcyh4PW5GZWF0dXJlX1JOQSwgeT1wZXJjZW50Lm1pdG8pKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWF4Lm1pdG8udGhyKSwgY29sb3VyID0gInJlZCIsIGxpbmV0eXBlID0gMikgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtaW4ubWl0by50aHIpLCBjb2xvdXIgPSAicmVkIiwgbGluZXR5cGUgPSAyKSArCiAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgbGFiZWwgPSBwYXN0ZTAoYXMubnVtZXJpYyh0YWJsZShDZWxsLlFDLlN0YXQkcGVyY2VudC5taXRvID4gbWF4Lm1pdG8udGhyIHwgQ2VsbC5RQy5TdGF0JHBlcmNlbnQubWl0byA8IG1pbi5taXRvLnRocilbMl0pLCIgY2VsbHMgcmVtb3ZlZFxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5udW1lcmljKHRhYmxlKENlbGwuUUMuU3RhdCRwZXJjZW50Lm1pdG8gPiBtYXgubWl0by50aHIgfCBDZWxsLlFDLlN0YXQkcGVyY2VudC5taXRvIDwgbWluLm1pdG8udGhyKVsxXSksIiBjZWxscyByZW1haW4iKSwKICAgICAgICAgICB4ID0gNjAwMCwgeSA9IDIwKQoKZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiLCBiaW5zPTEwMCkgCmBgYApgYGB7cn0KIyBGaWx0ZXIgY2VsbHMgYmFzZWQgb24gdGhlc2UgdGhyZXNob2xkcwpDZWxsLlFDLlN0YXQgPC0gQ2VsbC5RQy5TdGF0ICU+JSBmaWx0ZXIocGVyY2VudC5taXRvIDwgbWF4Lm1pdG8udGhyKSAlPiUgZmlsdGVyKHBlcmNlbnQubWl0byA+IG1pbi5taXRvLnRocikKYGBgCgojIyBGaWx0ZXJpbmcgY2VsbHMgYmFzZWQgb24gbnVtYmVyIG9mIGdlbmVzIGFuZCB0cmFuc2NyaXB0cyBkZXRlY3RlZAoKIyMjIFJlbW92ZSBjZWxscyB3aXRoIHRvIGZldyBnZW5lIGRldGVjdGVkIG9yIHdpdGggdG8gbWFueSBVTUkgY291bnRzCgpXZSBmaWx0ZXIgY2VsbHMgd2hpY2ggYXJlIGxpa2VseSB0byBiZSBkb3VibGV0IGJhc2VkIG9uIHRoZWlyIGhpZ2hlciBjb250ZW50IG9mIHRyYW5zY3JpcHQgZGV0ZWN0ZWQgYXMgd2VsbCBhcyBjZWxsIHdpdGggdG8gZmV3IGdlbmVzL1VNSSBzZXF1ZW5jZWQKCmBgYHtyfQojIFNldCBsb3cgYW5kIGhpZ2h0IHRocmVzaG9sZHMgb24gdGhlIG51bWJlciBvZiBkZXRlY3RlZCBnZW5lcyBiYXNlZCBvbiB0aGUgb25lIG9idGFpbiB3aXRoIHRoZSBXVCBkYXRhc2V0Cm1pbi5HZW5lcy50aHIgPC0gbG9nMTAoMTYzNSkKbWF4LkdlbmVzLnRociA8LSBsb2cxMCg4MDY5KQoKIyBTZXQgaGlnaHQgdGhyZXNob2xkIG9uIHRoZSBudW1iZXIgb2YgdHJhbnNjcmlwdHMKbWF4Lm5VTUkudGhyIDwtIGxvZzEwKDU4OTU4KQpgYGAKCgpgYGB7cn0KIyBHZW5lL1VNSSBzY2F0dGVyIHBsb3QgYmVmb3JlIGZpbHRlcmluZwpwMSA8LSBnZ3Bsb3QoQ2VsbC5RQy5TdGF0LCBhZXMoeD1sb2cxMChuQ291bnRfUk5BKSwgeT1sb2cxMChuRmVhdHVyZV9STkEpKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWluLkdlbmVzLnRociksIGNvbG91ciA9ICJncmVlbiIsIGxpbmV0eXBlID0gMikgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtYXguR2VuZXMudGhyKSwgY29sb3VyID0gImdyZWVuIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1heC5uVU1JLnRociksIGNvbG91ciA9ICJyZWQiLCBsaW5ldHlwZSA9IDIpCgpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpCmBgYApgYGB7cn0KIyBGaWx0ZXIgY2VsbHMgYmFzZSBvbiBib3RoIG1ldHJpY3MKQ2VsbC5RQy5TdGF0IDwtIENlbGwuUUMuU3RhdCAlPiUgZmlsdGVyKGxvZzEwKG5GZWF0dXJlX1JOQSkgPiBtaW4uR2VuZXMudGhyKSAlPiUgZmlsdGVyKGxvZzEwKG5Db3VudF9STkEpIDwgbWF4Lm5VTUkudGhyKQpgYGAKCiMjIyBGaWx0ZXIgY2VsbHMgYmVsb3cgdGhlIG1haW4gcG9wdWxhdGlvbiBuVU1JL25HZW5lIHJlbGF0aW9uc2hpcAoKYGBge3J9CmxtLm1vZGVsIDwtIGxtKGRhdGEgPSBDZWxsLlFDLlN0YXQsIGZvcm11bGEgPSBsb2cxMChuRmVhdHVyZV9STkEpIH4gbG9nMTAobkNvdW50X1JOQSkpCgpwMiA8LSBnZ3Bsb3QoQ2VsbC5RQy5TdGF0LCBhZXMoeD1sb2cxMChuQ291bnRfUk5BKSwgeT1sb2cxMChuRmVhdHVyZV9STkEpKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWluLkdlbmVzLnRociksIGNvbG91ciA9ICJncmVlbiIsIGxpbmV0eXBlID0gMikgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSBtYXguR2VuZXMudGhyKSwgY29sb3VyID0gImdyZWVuIiwgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1heC5uVU1JLnRociksIGNvbG91ciA9ICJyZWQiLCBsaW5ldHlwZSA9IDIpICsKICBhbm5vdGF0ZShnZW9tID0gInRleHQiLCBsYWJlbCA9IHBhc3RlMChkaW0oQ2VsbC5RQy5TdGF0KVsxXSwgIiBRQyBwYXNzZWQgY2VsbHMiKSwgeCA9IDQsIHkgPSAzLjgpCgpnZ01hcmdpbmFsKHAyLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpCmBgYAojIyBGaWx0ZXIgdGhlIFNldXJhdCBvYmplY3QKCmBgYHtyfQpSYXcuZGF0YSA8LSBzdWJzZXQoeCA9IFJhdy5kYXRhLCBzdWJzZXQgPSBCYXJjb2RlcyAlaW4lICBDZWxsLlFDLlN0YXQkQmFyY29kZXMpCmBgYAoKYGBge3J9CiMgUGxvdCBmaW5hbCBRQyBtZXRyaWNzClZsblBsb3Qob2JqZWN0ID0gUmF3LmRhdGEsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwibkNvdW50X1JOQSIsICJwZXJjZW50Lm1pdG8iLCAicGVyY2VudC5yaWJvIiksIG5jb2w9IDIpICYgTm9BeGVzKCkKYGBgCmBgYHtyfQpwMSA8LSBnZ3Bsb3QoUmF3LmRhdGFAbWV0YS5kYXRhLCBhZXMoeD1sb2cxMChuQ291bnRfUk5BKSwgeT1sb2cxMChuRmVhdHVyZV9STkEpKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikKZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKQpgYGAKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgIlJhdy5kYXRhIl0pCmBgYAoKCiMgVXNlIFNjcnVibGV0IHRvIGRldGVjdCBvYnZpb3VzIGRvdWJsZXRzCgojIyBSdW4gU2NydWJsZXQgd2l0aCBkZWZhdWx0IHBhcmFtZXRlcgoKRXhwb3J0IHJhdyBjb3VudCBtYXRyaXggYXMgaW5wdXQgdG8gU2NydWJsZXQKCmBgYHtyfQojRXhwb3J0IGZpbHRlcmVkIG1hdHJpeApkaXIuY3JlYXRlKCIuLi8uLi9SYXdEYXRhL0dtbmNfS08vU2NydWJsZXRfaW5wdXRzIikKCmV4cHJEYXRhIDwtIE1hdHJpeChhcy5tYXRyaXgoUmF3LmRhdGFAYXNzYXlzW1siUk5BIl1dQGNvdW50cyksIHNwYXJzZSA9IFRSVUUpCndyaXRlTU0oZXhwckRhdGEsICIuLi8uLi9SYXdEYXRhL0dtbmNfS08vU2NydWJsZXRfaW5wdXRzL21hdHJpeDEubXR4IikKYGBgCmBgYHtweXRob259CmltcG9ydCBzY3J1YmxldCBhcyBzY3IKaW1wb3J0IHNjaXB5LmlvCmltcG9ydCBudW1weSBhcyBucAppbXBvcnQgb3MKCiNMb2FkIHJhdyBjb3VudHMgbWF0cml4IGFuZCBnZW5lIGxpc3QKaW5wdXRfZGlyID0gJy4uLy4uL1Jhd0RhdGEvR21uY19LTy9TY3J1YmxldF9pbnB1dHMnCmNvdW50c19tYXRyaXggPSBzY2lweS5pby5tbXJlYWQoaW5wdXRfZGlyICsgJy9tYXRyaXgxLm10eCcpLlQudG9jc2MoKQoKI0luaXRpYWxpemUgU2NydWJsZXQKc2NydWIgPSBzY3IuU2NydWJsZXQoY291bnRzX21hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWRfZG91YmxldF9yYXRlPTAuMSwKICAgICAgICAgICAgICAgICAgICAgc2ltX2RvdWJsZXRfcmF0aW89MiwKICAgICAgICAgICAgICAgICAgICAgbl9uZWlnaGJvcnMgPSA4KQoKI1J1biB0aGUgZGVmYXVsdCBwaXBlbGluZQpkb3VibGV0X3Njb3JlcywgcHJlZGljdGVkX2RvdWJsZXRzID0gc2NydWIuc2NydWJfZG91YmxldHMobWluX2NvdW50cz0xLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9jZWxscz0zLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9nZW5lX3ZhcmlhYmlsaXR5X3BjdGw9ODUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9wcmluX2NvbXBzPTI1KQpgYGAKCmBgYHtyfQojIEltcG9ydCBzY3J1YmxldCdzIGRvdWJsZXQgc2NvcmUKUmF3LmRhdGEkRG91YmxldHNjb3JlIDwtIHB5JGRvdWJsZXRfc2NvcmVzCgojIFBsb3QgZG91YmxldCBzY29yZQpnZ3Bsb3QoUmF3LmRhdGFAbWV0YS5kYXRhLCBhZXMoeCA9IERvdWJsZXRzY29yZSwgc3RhdChuZGVuc2l0eSkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDIwMCwgY29sb3VyID0ibGlnaHRncmV5IikrCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC4xNSwgY29sb3VyID0gInJlZCIsIGxpbmV0eXBlID0gMikKYGBgCmBgYHtyfQojIE1hbnVhbGx5IHNldCB0aHJlc2hvbGQgYXQgZG91YmxldCBzY29yZSB0byAwLjIKUmF3LmRhdGEkUHJlZGljdGVkX2RvdWJsZXRzIDwtIGlmZWxzZShweSRkb3VibGV0X3Njb3JlcyA+IDAuMTUsICJEb3VibGV0IiwiU2luZ2xldCIpCnRhYmxlKFJhdy5kYXRhJFByZWRpY3RlZF9kb3VibGV0cykKYGBgCmBgYHtyfQpSYXcuZGF0YSA8LSBzdWJzZXQoeCA9IFJhdy5kYXRhLCBzdWJzZXQgPSBQcmVkaWN0ZWRfZG91YmxldHMgPT0gIlNpbmdsZXQiKQpgYGAKCiMgR2VuZXJhdGUgU1JJTkcgZGltZW50aW9uYWxpdHkgcmVkdWN0aW9uCgojIyBFeHBvcnQgY291bnRzIG1hdHJpeAoKYGBge3J9CmRpci5jcmVhdGUoIi4vU3ByaW5nQ29vcmRpbmF0ZXMiKQpgYGAKCmBgYHtyfQojIEV4cG9ydCByYXcgZXhwcmVzc2lvbiBtYXRyaXggYW5kIGdlbmUgbGlzdCB0byByZWdlbmVyYXRlIGEgc3ByaW5nIHBsb3QKZXhwckRhdGEgPC0gTWF0cml4KGFzLm1hdHJpeChSYXcuZGF0YUBhc3NheXNbWyJSTkEiXV1AY291bnRzKSwgc3BhcnNlID0gVFJVRSkKd3JpdGVNTShleHByRGF0YSwgIi4vU3ByaW5nQ29vcmRpbmF0ZXMvRXhwckRhdGEubXR4IikKYGBgCgpgYGB7cn0KR2VuZWxpc3QgPC0gcm93Lm5hbWVzKFJhdy5kYXRhQGFzc2F5c1tbIlJOQSJdXUBjb3VudHMpCndyaXRlLnRhYmxlKEdlbmVsaXN0LCAiLi9TcHJpbmdDb29yZGluYXRlcy9HZW5lbGlzdC5jc3YiLCBzZXA9Ilx0IiwgY29sLm5hbWVzID0gRiwgcm93Lm5hbWVzID0gRiwgcXVvdGUgPSBGKQpgYGAKCmBgYHtyfQojRXhwb3J0IG1ldGFkYXRhClNjcnVibGV0IDwtIGMoIlNjcnVibGV0IiwgUmF3LmRhdGEkUHJlZGljdGVkX2RvdWJsZXRzKQpTY3J1YmxldCA8LSBwYXN0ZShTY3J1YmxldCwgc2VwPSIsIiwgY29sbGFwc2U9IiwiKQoKQ2VsbGdyb3VwaW5nIDwtIFNjcnVibGV0CndyaXRlLnRhYmxlKENlbGxncm91cGluZywgIi4vU3ByaW5nQ29vcmRpbmF0ZXMvQ2VsbGdyb3VwaW5nLmNzdiIsIHF1b3RlID1GLCByb3cubmFtZXMgPSBGLCBjb2wubmFtZXMgPSBGKQpgYGAKCiMjIEltcG9ydCBjb29yZGluYXRlcwoKYGBge3J9CnNwcmluZy5jb29yIDwtIHJlYWQudGFibGUoIlNwcmluZ0Nvb3JkaW5hdGVzL2Nvb3JkaW5hdGVzLnR4dCIsIHNlcCA9ICIsIiwgaGVhZGVyID0gRiwgcm93Lm5hbWVzID0gMSkKY29sbmFtZXMoc3ByaW5nLmNvb3IpIDwtIGMoIlNwcmluZ18xIiwgIlNwcmluZ18yIikKYGBgCgpgYGB7cn0KU3ByaW5nLlN5bSA8LSBmdW5jdGlvbih4KXsKICB4ID0gYWJzKG1heChzcHJpbmcuY29vciRTcHJpbmdfMikteCkKIH0KCnNwcmluZy5jb29yJFNwcmluZ18yIDwtIHNhcHBseShzcHJpbmcuY29vciRTcHJpbmdfMiwgZnVuY3Rpb24oeCkgU3ByaW5nLlN5bSh4KSkKYGBgCgpgYGB7cn0KUmF3LmRhdGEkU3ByaW5nXzEgPC0gc3ByaW5nLmNvb3IkU3ByaW5nXzEKUmF3LmRhdGEkU3ByaW5nXzIgPC0gc3ByaW5nLmNvb3IkU3ByaW5nXzIKYGBgCgoKYGBge3J9CnNwcmluZyA8LSBhcy5tYXRyaXgoUmF3LmRhdGFAbWV0YS5kYXRhICU+JSBzZWxlY3QoIlNwcmluZ18xIiwgIlNwcmluZ18yIikpCiAgClJhdy5kYXRhW1sic3ByaW5nIl1dIDwtIENyZWF0ZURpbVJlZHVjT2JqZWN0KGVtYmVkZGluZ3MgPSBzcHJpbmcsIGtleSA9ICJTcHJpbmdfIiwgYXNzYXkgPSBEZWZhdWx0QXNzYXkoUmF3LmRhdGEpKQpgYGAKCmBgYHtyfQpEaW1QbG90KFJhdy5kYXRhLCAKICAgICAgICByZWR1Y3Rpb24gPSAic3ByaW5nIiwKICAgICAgICBwdC5zaXplID0gMC41KSAmIE5vQXhlcygpCmBgYAojIFNjdHJhbnNmb3JtIG5vcm1hbGl6YXRpb24KCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9ClJhdy5kYXRhIDwtIFNDVHJhbnNmb3JtKFJhdy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiZ2xtR2FtUG9pIiwKICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5yZWdyZXNzID0gYygicGVyY2VudC5taXRvIiksCiAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUKQpgYGAKIyBSdW4gUENBIGFuZCBicm9hZCBjbHVzdGVyaW5nCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQpSYXcuZGF0YSA8LSBSdW5QQ0EoUmF3LmRhdGEsIHZlcmJvc2UgPSBGQUxTRSkKClJhdy5kYXRhIDwtIEZpbmROZWlnaGJvcnMoUmF3LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcyA9IDE6MjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgay5wYXJhbSA9IDgpCgpSYXcuZGF0YSA8LSBGaW5kQ2x1c3RlcnMoUmF3LmRhdGEsIHJlc29sdXRpb24gPSAwLjIpCmBgYAoKYGBge3J9CkRpbVBsb3QoUmF3LmRhdGEsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgY29scyA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsICIjMDQ2YzlhIiwgIiM0OTkwYzkiKSwKICAgICAgICBwdC5zaXplID0gMC41KSAmIE5vQXhlcygpCmBgYApgYGB7cn0KUmF3LmRhdGEkQnJvYWRjbHVzdC5pZGVudCA8LSBSYXcuZGF0YSRzZXVyYXRfY2x1c3RlcnMKYGBgCgojIERpZmZlcmVudGlhdGluZyBuZXVyb25zIHN1Yi1jbHVzdGVyaW5nCgojIyBFeHRyYWN0IGRpZmZlcmVudGlhdGluZyBuZXVyb25zCgpgYGB7cn0KTmV1cm9ucy5kYXRhIDwtICBzdWJzZXQoUmF3LmRhdGEsIGlkZW50cyA9IDMpCgpEaW1QbG90KE5ldXJvbnMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24gPSAic3ByaW5nIiwKICAgICAgICBwdC5zaXplID0gMSwKICAgICAgICBjb2xzID0gIGMoIiNjYzNhMWIiKSkgKyBOb0F4ZXMoKQpgYGAKIyMgRml0IHBzZXVkb3RpbWUKCmBgYHtyfQpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChOZXVyb25zLmRhdGFAbWV0YS5kYXRhWyxjKCJTcHJpbmdfMSIsICJTcHJpbmdfMiIpXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTApCmBgYAoKYGBge3J9CiNQc2V1ZG90aW1lIHNjb3JlClBzZXVkb3RpbWVTY29yZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKQoKaWYgKGNvcihQc2V1ZG90aW1lU2NvcmUsIE5ldXJvbnMuZGF0YUBhc3NheXMkU0NUQGRhdGFbJ0htZ2EyJywgXSkgPiAwKSB7CiAgTmV1cm9ucy5kYXRhJFBzZXVkb3RpbWVTY29yZSA8LSAtKFBzZXVkb3RpbWVTY29yZSAtIG1heChQc2V1ZG90aW1lU2NvcmUpKQp9Cgpjb2xzIDwtIGJyZXdlci5wYWwobiA9MTEsIG5hbWUgPSAiU3BlY3RyYWwiKQoKZ2dwbG90KE5ldXJvbnMuZGF0YUBtZXRhLmRhdGEsIGFlcyhTcHJpbmdfMSwgU3ByaW5nXzIpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9UHNldWRvdGltZVNjb3JlKSwgc2l6ZT0yLCBzaGFwZT0xNikgKyAKICBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3Vycz1yZXYoY29scyksIG5hbWU9J1BzZXVkb3RpbWUgc2NvcmUnKQpgYGAKIyMgUmVncmVzcyBwc2V1ZG90aW1lIGFuZCBjbHVzdGVyIGNlbGxzIGludG8gbGluZWFnZXMKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9Ck5ldXJvbnMuZGF0YSA8LSBTQ1RyYW5zZm9ybShOZXVyb25zLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiZ2xtR2FtUG9pIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcnMudG8ucmVncmVzcyA9IGMoIlBzZXVkb3RpbWVTY29yZSIsICJuRmVhdHVyZV9STkEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUKQoKYGBgCgpXZSB1c2VkIG9uIHRyYW5zY3JpcHRpb24gZmFjdG9ycyBleHByZXNzaW9uIHByb2ZpbGUgdG8gcGVyZm9ybSBsaW5lYWdlIGNsdXN0ZXJpbmcKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9ClRGcyA8LSByZWFkLnRhYmxlKCJURi5jc3YiLCBzZXAgPSAiOyIpWywxXQoKTmV1cm9ucy5kYXRhIDwtIFJ1blBDQShOZXVyb25zLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZXMgPSBURnMsCiAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IEZBTFNFKQpgYGAKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9Ck5ldXJvbnMuZGF0YSA8LSBGaW5kTmVpZ2hib3JzKE5ldXJvbnMuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1zID0gYygxOjEwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBrLnBhcmFtID0gNikKCk5ldXJvbnMuZGF0YSA8LSBGaW5kQ2x1c3RlcnMoTmV1cm9ucy5kYXRhLCByZXNvbHV0aW9uID0gMC4yKQoKRGltUGxvdChOZXVyb25zLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgY29scyA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsICIjMDQ2YzlhIiwgIiM0OTkwYzkiKSwKICAgICAgICBwdC5zaXplID0gMC41KSAmIE5vQXhlcygpCmBgYAoKYGBge3J9CkZlYXR1cmVQbG90KG9iamVjdCA9IE5ldXJvbnMuZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMgPSBjKCJGb3hnMSIsICJaZnBtMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiTGh4MSIsICJaaWM1IiwgIlpmcDUwMyIpLAogICAgICAgICAgICBwdC5zaXplID0gMC4yLAogICAgICAgICAgICBjb2xzID0gYygiZ3JleTkwIiwgYnJld2VyLnBhbCg5LCJZbEduQnUiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJzcHJpbmciLAogICAgICAgICAgICBvcmRlciA9IFQpICYgTm9BeGVzKCkgJiBOb0xlZ2VuZCgpCmBgYAoKYGBge3J9ClJhdy5kYXRhJEJyb2FkY2x1c3QuaWRlbnQgPC0gc2FwcGx5KFJhdy5kYXRhJEJhcmNvZGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSBmdW5jdGlvbih4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHggJWluJSBOZXVyb25zLmRhdGEkQmFyY29kZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBwYXN0ZTAoIk5ldXJvbl8iLE5ldXJvbnMuZGF0YUBtZXRhLmRhdGFbeCwgInNldXJhdF9jbHVzdGVycyJdKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gUmF3LmRhdGFAbWV0YS5kYXRhW3gsICJCcm9hZGNsdXN0LmlkZW50Il0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkKYGBgCgoKYGBge3J9CkRpbVBsb3QoUmF3LmRhdGEsCiAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgZ3JvdXAuYnkgPSAiQnJvYWRjbHVzdC5pZGVudCIsCiAgICAgICAgY29scyA9IGMoIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiZ3JleTkwIiwgIiNlNzgyM2EiLCAiIzA0NmM5YSIsICIjNDk5MGM5IiksCiAgICAgICAgcHQuc2l6ZSA9IDAuNSkgJiBOb0F4ZXMoKQpgYGAKCgojIFBsb3QgbWFya2VyIGdlbmVzIGZvdW5kIGluIHRoZSBXVCBkYXRhc2V0CgpgYGB7cn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gUmF3LmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gYygiVGJyMSIsIkZveGcxIiwgIlRycDczIiwgIkh0cjJjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJTaGlzYTIiLCAiV2lmMSIsICJSYXNzZjQiLCJEa2szIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJEbGsxIiwgIlN1bGYxIiwgIlR0ciIsICJGZ2Y4IiwgIkZnZjE3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICJGb3hjMSIsICJDMXFiIiksCiAgICAgICAgICAgIHB0LnNpemUgPSAwLjIsCiAgICAgICAgICAgIGNvbHMgPSBjKCJncmV5OTAiLCBicmV3ZXIucGFsKDksIllsR25CdSIpKSwKICAgICAgICAgICAgcmVkdWN0aW9uID0gInNwcmluZyIsCiAgICAgICAgICAgIG9yZGVyID0gVCkgJiBOb0F4ZXMoKSAmIE5vTGVnZW5kKCkKYGBgCgoKIyBTYXZlIHRoZSBvYmplY3QKCmBgYHtyIFNhdmUgUkRTfQpzYXZlUkRTKFJhdy5kYXRhLCAiLi9HbW5jS08uY2VsbHMuUkRTIikKYGBgCgoKIyBTZXNzaW9uIEluZm8KCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=